﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using LDSBusiness.EventArgs;
using LDSModel;
using LDSCore;
using LDSBusiness;
using LDSModel.Dal;
using LDSProject.Forms;
using LDSProject.Properties;

namespace LDSProject.Controls
{
    public partial class OilTankControl : UserControl
    {
        readonly Guid _oilTankId;
        List<Data_Device> _deviceList;
        Dictionary<int, List<Data_Records>> _dataList;
        readonly Dictionary<object, Point> _posList;

        public OilTankControl(Guid oilTankId)
        {
            InitializeComponent();

            _oilTankId = oilTankId;
            _posList = new Dictionary<object, Point>();
        }

        ~OilTankControl()
        {
            timer1.Stop();
            MainConsole.Instance.OnRecordReceived -= DataService_OnRecordReceived;
            MainConsole.Instance.OnDeviceStateChanged -= DataService_OnDeviceStateChanged;
        }

        private void OilTankControl_Load(object sender, EventArgs e)
        {
            _dataList = new Dictionary<int, List<Data_Records>>();
            var oilTank = DeviceService.Instance.GetOilTank(_oilTankId);

            Text = oilTank.Name;
            lbTitle.Text = oilTank.Name;

            _deviceList = DeviceService.Instance.LoadDeviceList(_oilTankId);

            var blWidth = (float)Width / BackgroundImage.Width;
            var blHeight = (float)Height / BackgroundImage.Height;
            var bl = Math.Min(blWidth, blHeight);

            foreach (Control control in Controls.Cast<Control>().Where(control => control is Panel && control.Tag != null))
            {
                _posList.Add(control.Tag, new Point { X = (int)(control.Left / bl), Y = (int)(control.Top / bl) });
            }

            var index = 1;

            foreach (var device in _deviceList)
            {
                if (device != null)
                {
                    if (MainConsole.Instance.DevicePostion.ContainsKey(device.Index.Value))
                    {
                        var point = MainConsole.Instance.DevicePostion[device.Index.Value];

                        var pb = new PictureBox
                            {
                                Left = (int)(point.X * bl),
                                Top = (int)(point.Y * bl),
                                Name = device.DeviceId.ToString(),
                                Tag = "pbTank" + device.Position + "|pbDevice" + index++
                            };
                        pb.MouseDoubleClick += pb_MouseDoubleClick;
                        pb.MouseEnter += MainConsole.Instance.pb_MouseEnter;
                        pb.MouseLeave += MainConsole.Instance.pb_MouseLeave;

                        pb.BackgroundImage = Resources.device;
                        pb.BackgroundImageLayout = ImageLayout.Stretch;
                        pb.BackColor = Color.Transparent;
                        pb.Cursor = Cursors.Hand;
                        pb.Width = (int)(38 * bl);
                        pb.Height = (int)(29 * bl);
                        pb.SizeMode = PictureBoxSizeMode.StretchImage;

                        pb.Image = Resources.offline;
                        pb.BackColor = Color.Transparent;
                        pb.Enabled = false;

                        Controls.Add(pb);
                    }
                }

                if (device == null) continue;
                MainConsole.Instance.CheckDeviceState(device.DeviceId, DataService_OnDeviceStateChanged, null);

                if (device.Position != null && !_dataList.Keys.Contains(device.Position.Value))
                    _dataList.Add(device.Position.Value, new List<Data_Records>());
            }

            MainConsole.Instance.OnRecordReceived += DataService_OnRecordReceived;
            MainConsole.Instance.OnDeviceStateChanged += DataService_OnDeviceStateChanged;
            MainConsole.Instance.OnPortStop += Instance_OnPortStop;
            timer1.Start();
        }

        void Instance_OnPortStop()
        {
            foreach (var device in DeviceService.Instance.LoadDeviceList(_oilTankId))
            {
                Invoke(new DelegateRefreshDevice(MainConsole.Instance.RefreshPictureBox), this, device.DeviceId, DeviceState.Offline);
            }

            _dataList.Clear();

            foreach (var device in _deviceList)
            {
                var pb = Controls.Find(device.DeviceId.ToString(), false).FirstOrDefault() as PictureBox;
                if (null == pb) continue;
                var panel = Controls.Find(pb.Tag.ToString().Split('|')[0], false).FirstOrDefault() as Panel;

                if (!IsDisposed)
                    Invoke(new DelegateRefreshValue1(MainConsole.Instance.RefreshValue), device.DeviceId, panel, _dataList);
            }
        }

        void DataService_OnDeviceStateChanged(object sender, DeviceStateChangedEventArgs args)
        {
            if (!IsDisposed)
                Invoke(new DelegateRefreshDevice(MainConsole.Instance.RefreshPictureBox), this, args.DeviceId, args.State);
            var pb = Controls.Find(args.DeviceId.ToString(), false).FirstOrDefault() as PictureBox;
            if (null == pb) return;
            var panel = Controls.Find(pb.Tag.ToString().Split('|')[0], false).FirstOrDefault() as Panel;

            if (!IsDisposed)
                Invoke(new DelegateRefreshValue1(MainConsole.Instance.RefreshValue), args.DeviceId, panel, _dataList);
        }

        void DataService_OnRecordReceived(object sender, RecordReceivedEventArgs args)
        {
            var device = DeviceService.Instance.GetDevice(args.Record.DeviceID);

            if (device == null || device.OID != _oilTankId) return;
            lock (_dataList)
            {
                List<Data_Records> records;
                _dataList.TryGetValue(device.Position.Value, out records);

                if (records == null)
                {
                    records = new List<Data_Records>();
                }
                else
                {
                    _dataList.Remove(device.Position.Value);
                }

                records.Add(args.Record);
                _dataList.Add(device.Position.Value, records);
            }

            if (!IsDisposed && MainConsole.Instance.CheckAlermValue(args.Record))
                Invoke(new DelegateRefreshDevice(MainConsole.Instance.RefreshPictureBox), this, args.Record.DeviceID, DeviceState.Alarm);
            var pb = Controls.Find(device.DeviceId.ToString(), false).FirstOrDefault() as PictureBox;
            if (null == pb) return;
            var panel = Controls.Find(pb.Tag.ToString().Split('|')[0], false).FirstOrDefault() as Panel;

            if (!IsDisposed)
                Invoke(new DelegateRefreshValue1(MainConsole.Instance.RefreshValue), args.Record.DeviceID, panel, _dataList);
        }

        private void pb_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;
            if (!MainConsole.Instance.CheckPortIsOpen(this)) return;
            var form = new DeviceForm(Guid.Parse(((PictureBox)sender).Name));
            form.ShowDialog(this);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            lock (_dataList)
            {
                try
                {
                    foreach (var device in _deviceList)
                    {
                        List<Data_Records> records;
                        _dataList.TryGetValue(device.Position.Value, out records);

                        if (null != records && records.Count > 0)
                        {
                            records = records.FindAll(r => r.AlarmTime != null && DateTime.Now.Subtract(r.AlarmTime.Value).TotalSeconds < Settings.Default.AlermTimeOut);

                            _dataList.Remove(device.Position.Value);
                            _dataList.Add(device.Position.Value, records);
                        }

                        var pb = Controls.Find(device.DeviceId.ToString(), false).FirstOrDefault() as PictureBox;
                        if (null == pb) continue;
                        var panel = Controls.Find(pb.Tag.ToString().Split('|')[0], false).FirstOrDefault() as Panel;

                        if (!IsDisposed)
                            Invoke(new DelegateRefreshValue1(MainConsole.Instance.RefreshValue), device.DeviceId, panel, _dataList);

                        var alermTime = MainConsole.Instance.DeviceAlermTimeList.FirstOrDefault(d => d.Key == device.DeviceId).Value;
                        if (!(DateTime.Now.Subtract(alermTime).TotalSeconds > Settings.Default.AlermTimeOut))
                            continue;
                        if (Utils.Same(Resources.light__2_, pb.Image))
                            Invoke(new DelegateRefreshDevice(MainConsole.Instance.RefreshPictureBox), this, device.DeviceId, DeviceState.Online);
                    }
                }
                catch (Exception ex)
                {
                    LogFileHelper.Record(ex);
                }
            }
        }

        private void OilTankControl_Resize(object sender, EventArgs e)
        {
            var size = new Size(38, 29);
            var blWidth = (float)Width / BackgroundImage.Width;
            var blHeight = (float)Height / BackgroundImage.Height;
            var bl = Math.Min(blWidth, blHeight);
            var offsetWidth = 0;
            var offsetHeight = 0;
            if (blWidth > blHeight)
            {
                offsetWidth = (Width - (int)(BackgroundImage.Width * bl)) / 2;
            }
            else
            {
                offsetHeight = (Height - (int)(BackgroundImage.Height * bl)) / 2;
            }

            foreach (Control control in this.Controls)
            {
                var box = control as PictureBox;
                if (box != null)
                {
                    var pic = box;
                    Point point;
                    MainConsole.Instance.DevicePostion.TryGetValue(int.Parse(pic.Tag.ToString().Split('|')[1].Replace("pbDevice", "")), out point);
                    if (!point.IsEmpty)
                    {
                        pic.Left = offsetWidth + (int)(point.X * bl);
                        pic.Top = offsetHeight + (int)(point.Y * bl);
                        pic.Width = (int)(size.Width * bl);
                        pic.Height = (int)(size.Height * bl);
                    }
                }
                else if (control is Panel)
                {
                    if (control.Tag != null && _posList.Count > 0)
                    {
                        control.Left = (int)(_posList[control.Tag].X * bl);
                        control.Top = (int)(_posList[control.Tag].Y * bl);
                    }
                }
            }
        }
    }
}
